package com.pomelo.base.core.util;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;


/**
 * @author mengbin
 * @date 2019年9月10日 下午6:34:02
 */
public class ThreadUtil {

    private static ThreadPoolTaskExecutor executor = null;

    public static final String BEAN_ID = "myThreadPool";

    @Value("${app.thread.pool.queueCapacity:20}")
    private static int queueCapacity;

    @Value("${app.thread.pool.corePoolSize:20}")
    private static int corePoolSize;

    @Value("${app.thread.pool.maxPoolSize:50}")
    private static int maxPoolSize;

    @Value("${app.thread.pool.keepAliveSeconds:60}")
    private static int keepAliveSeconds;

    private ThreadUtil() {

    }

    public static ThreadPoolTaskExecutor getExecutor() {
        if (executor == null) {
            executor = myThreadPool();
        }
        return executor;
    }

    public static void execute(Runnable task) {
        getExecutor().execute(task);
    }

    public static Future<?> submit(Runnable task) {
        return getExecutor().submit(task);
    }

    public static <T> Future<T> submit(Callable<T> task) {
        return getExecutor().submit(task);
    }

    @Bean(name = BEAN_ID, destroyMethod = "shutdown")
    public static ThreadPoolTaskExecutor myThreadPool() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}
